﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using AxWMPLib;

namespace RhythmGame
{
    public partial class Game : Form
    {
        internal string songName;
        internal string beatMapFileName;
        internal bool playVideo;
        private BeatMap map;
        private System.Windows.Forms.Timer interfaceTimer;
        private System.Windows.Forms.Timer time;
        private System.Windows.Forms.Timer endGameTimer;
        private Stopwatch stopWatch;
        private int lastElapsedMilliseconds;
        private int lastFrameTime;

        private bool isPaused = false;        

        internal List<NoteTap> currentTaps = new List<NoteTap>();
        internal List<NoteBreakTap> currentBreakTaps = new List<NoteBreakTap>();
        internal List<NoteDrag> currentDrags = new List<NoteDrag>();
        internal List<ProtectedTap> currentProtectedTap = new List<ProtectedTap>();
        internal List<ProtectedBreakTap> currentProtectedBreakTap = new List<ProtectedBreakTap>();

        private Thread judgementThread;
        internal readonly object lockObject = new object();

        internal List<Tuple<Keys, int>> keysPress = new List<Tuple<Keys, int>>();
        internal List<NoteTap> tapsToRemove = new List<NoteTap>();
        internal List<NoteBreakTap> breakTapsToRemove = new List<NoteBreakTap>();
        internal List<NoteDrag> dragsToRemove = new List<NoteDrag>();
        internal List<ProtectedTap> protectedTapsToRemove = new List<ProtectedTap>();
        internal List<ProtectedBreakTap> protectedBreakTapsToRemove = new List<ProtectedBreakTap>();

        public Game()
        {
            InitializeComponent();

            this.songName = Settings.Instance.CurrentSongName;
            this.beatMapFileName = "beatmap.rg";

            map = BeatMapLoader.Instance.LoadBeatMap(songName, beatMapFileName);

            playVideo = map.VideoPath != null && map.VideoPath != "" && Settings.Instance.SetVideoVisible;

            //this.FormBorderStyle = FormBorderStyle.None; // 无边框
            this.TopMost = Settings.Instance.IsTop; // 窗口是否置顶

            //this.WindowState = FormWindowState.Maximized; // 最大化

            this.BackColor = Settings.Instance.BackgroundColor; // 背景色

            //this.TransparencyKey = Color.Black; // 透明色
            
            //this.Opacity = 0.5; // 窗口透明度

            this.SetClientSizeCore(Settings.Instance.WinWidth, Settings.Instance.WinHeight); // 窗口大小

            //// 禁止窗口调整大小
            //this.FormBorderStyle = FormBorderStyle.FixedSingle;
            //this.MaximizeBox = false;



            //this.BackgroundImage = Image.FromFile(map.BackgroundPath); // 背景图

            MessageBox.Show("歌曲名称：" + map.Name + '\n'
                + "作曲：" + map.Artist + '\n'
                + "制谱：" + map.Mapper + '\n'
                + "难度：" + map.Difficulty + '\n'
                + "时长：" + map.Time);

            //BackgroundLoader.LoadStartInterface(this, map);


            switch (Settings.Instance.ScoringMethod)
            {
                case 1:
                    this.labelAccuracy.Text = "100.0000%";
                    break;
                case 2:
                    this.labelAccuracy.Text = "0.0000%";
                    break;
                case 3:
                    this.labelAccuracy.Text = map.HasBreakNotes() ? "101.0000%" : "100.0000%";
                    break;
                default:
                    this.labelAccuracy.Text = "--.----%";
                    break;
            }
            Scoring.InitializeAccuracy(map);

            this.Resize += new EventHandler(OnResize);

            this.KeyPreview = true;
            this.KeyDown += new KeyEventHandler(OnKeyDown);
            this.KeyUp += new KeyEventHandler(OnKeyUp);
            

            JudgeLine.ShowLine(this);

            this.endGameTimer = new System.Windows.Forms.Timer();
            this.endGameTimer.Interval = 8000; // 8秒
            this.endGameTimer.Tick += EndGameTimer_Tick;

            this.time = new System.Windows.Forms.Timer();
            this.stopWatch = new Stopwatch();
            this.time.Interval = 1000 / Settings.Instance.FPS; // default 60 FPS
            this.time.Tick += Update;
                        
            this.lastElapsedMilliseconds = 0; // 初始化上一次经过的毫秒数

            
            BackgroundLoader.LoadBackground(this, map);


            this.time.Start();
            this.stopWatch.Start();

            // 初始化并启动判定线程
            this.judgementThread = new Thread(JudgementLoop);
            this.judgementThread.IsBackground = true;
            this.judgementThread.Start();

            
        }

        public void SetLabelComboText(string text)
        {
            if (this.labelCombo.InvokeRequired)
            {
                this.labelCombo.Invoke(new Action<string>(SetLabelComboText), text);
            }
            else
            {
                this.labelCombo.Text = text;
            }
        }

        public void SetLabelDecideText(string text)
        {
            if (this.labelDecide.InvokeRequired)
            {
                this.labelDecide.Invoke(new Action<string>(SetLabelDecideText), text);
            }
            else
            {
                this.labelDecide.Text = text;
            }
        }

        public void SetLabelDecideColor(Color color)
        {
            if (this.labelDecide.InvokeRequired)
            {
                this.labelDecide.Invoke(new Action<Color>(SetLabelDecideColor), color);
            }
            else
            {
                this.labelDecide.ForeColor = color;
            }
        }

        public void SetLabelScoreText(string text)
        {
            if (this.labelDecide.InvokeRequired)
            {
                this.labelDecide.Invoke(new Action<string>(SetLabelScoreText), text);
            }
            else
            {
                this.labelScore.Text = text;
            }
        }

        public void SetLabelAccuracyText(string text)
        {
            if (this.labelDecide.InvokeRequired)
            {
                this.labelDecide.Invoke(new Action<string>(SetLabelAccuracyText), text);
            }
            else
            {
                this.labelAccuracy.Text = text;
            }
        }

        private void Update(object sender, EventArgs e)
        {            
            // 获取当前经过的时间
            int elapsedMillisecondsFPS = (int)stopWatch.Elapsed.TotalMilliseconds;

            // 计算 FPS
            int frameTime = elapsedMillisecondsFPS - lastFrameTime;
            int fps = frameTime > 0 ? 1000 / frameTime : 0;
            lastFrameTime = elapsedMillisecondsFPS;

            // 更新 FPS 标签
            this.labelFPS.Text = "FPS: " + fps;

            // 获取当前经过的时间
            TimeSpan elapsedTime = stopWatch.Elapsed;
            int elapsedMilliseconds = (int)elapsedTime.TotalMilliseconds;

            // 检查是否到达 map.Time
            if (elapsedTime >= map.Time && !endGameTimer.Enabled)
            {
                endGameTimer.Start();
            }

            // 调整 lastTime 和 currentTime，提前 DuringTime
            int adjustedLastTime = lastElapsedMilliseconds + Settings.Instance.DuringTime;
            int adjustedCurrentTime = elapsedMilliseconds + Settings.Instance.DuringTime;
            Element_info[] blockElements = map.GetNextTickInfo(adjustedLastTime, adjustedCurrentTime);

            // 创建此时所有的 Tap 及相关物块
            NoteTap.NextTaps(this, map, currentTaps, blockElements);
            NoteBreakTap.NextTaps(this, map, currentBreakTaps, blockElements);
            NoteDrag.NextDrags(this, map, currentDrags, blockElements);
            ProtectedTap.NextTaps(this, map, currentProtectedTap, blockElements);
            ProtectedBreakTap.NextTaps(this, map, currentProtectedBreakTap, blockElements);
            // 移动 Tap 及相关物块
            NoteTap.TapsMove(this, currentTaps, elapsedMilliseconds);
            NoteBreakTap.TapsMove(this, currentBreakTaps, elapsedMilliseconds);
            NoteDrag.DragsMove(this, currentDrags, elapsedMilliseconds);
            ProtectedTap.TapsMove(this, currentProtectedTap, elapsedMilliseconds);
            ProtectedBreakTap.TapsMove(this, currentProtectedBreakTap, elapsedMilliseconds);


            // 更新上一次的时间
            this.lastElapsedMilliseconds = elapsedMilliseconds;
            
        }
        
        private void JudgementLoop()
        {
            while (true)
            {                
                int elapsedMilliseconds = (int)stopWatch.Elapsed.TotalMilliseconds;
                if (keysPress.Count > 0)
                {
                    NoteTap.Judgement(this, currentTaps, elapsedMilliseconds, keysPress);
                    NoteBreakTap.Judgement(this, currentBreakTaps, elapsedMilliseconds, keysPress);
                    NoteDrag.Judgement(this, currentDrags, elapsedMilliseconds, keysPress);
                    ProtectedTap.Judgement(this, currentProtectedTap, elapsedMilliseconds, keysPress);
                    ProtectedBreakTap.Judgement(this, currentProtectedBreakTap, elapsedMilliseconds, keysPress);

                    //keysPress.Clear();
                }
                
                Thread.Sleep(10); // 控制判定频率，睡眠 10 毫秒
            }
        }

        private void EndGameTimer_Tick(object sender, EventArgs e)
        {
            endGameTimer.Stop();

            //// 停止计时器
            //time.Stop();
            //stopWatch.Stop();

            this.TogglePause();

            // 获取分数、准确率和各判定的数量
            string score = this.labelScore.Text;
            string accuracy = this.labelAccuracy.Text;
            int criticalPerfectNum = Scoring.CriticalPerfectCount;
            int perfectNum = Scoring.PerfectCount;
            int greatNum = Scoring.GreatCount;
            int goodNum = Scoring.GoodCount;
            int missNum = Scoring.MissCount;
            // 获取时间
            DateTime CompleteTime = DateTime.Now;

            // 创建并保存分数记录
            ScoresRecord.BeatmapRecord record = new ScoresRecord.BeatmapRecord
            {
                Name = Settings.Instance.PlayerName,
                BeatMapName = Settings.Instance.CurrentSongName,
                Score = (int)Scoring.Score,
                Accuracy = accuracy,
                CritalPerfectCount = criticalPerfectNum,
                PerfectCount = perfectNum,
                GreatCount = greatNum,
                GoodCount = goodNum,
                MissCount = missNum,
                Time = CompleteTime
            };
            ScoresRecord.AddRecord(record);

            // 显示对话框
            MessageBox.Show($"游戏结束！\n分数: {score}\n准确率: {accuracy}\n" +
                $"Critical Perfect: {criticalPerfectNum}\n" + $"Perfect: {perfectNum}\n" +
                $"Great: {greatNum}\n" + $"Good: {goodNum}\n" + $"Miss: {missNum}\n",
                "游戏结束", MessageBoxButtons.OK, MessageBoxIcon.Information);

            // 退出游戏
            Application.Exit();
        }


        internal void OnKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                TogglePause();
                return;
            }

            lock (lockObject)
            {
                int pressTime = (int)stopWatch.Elapsed.TotalMilliseconds;
                if (!keysPress.Any(k => k.Item1 == e.KeyCode))
                {
                    keysPress.Add(new Tuple<Keys, int>(e.KeyCode, pressTime));
                }
            }
        }

        internal void OnKeyUp(object sender, KeyEventArgs e)
        {
            lock (lockObject)
            {
                var keyToRemove = keysPress.FirstOrDefault(k => k.Item1 == e.KeyCode);
                if (keyToRemove != null)
                {
                    keysPress.Remove(keyToRemove);
                }
            }
        }

        internal void OnResize(object sender, EventArgs e)
        {
            if (labelCombo != null)
            {
                // 计算 labelCombo 的新位置，使其左右居中
                int newX = (this.ClientSize.Width - labelCombo.Width) / 2;
                labelCombo.Location = new Point(newX, labelCombo.Location.Y);
            }
        }

        internal void TogglePause()
        {
            // VLC 控制
            if (BackgroundLoader.audioPlayer == null)
                return;

            if (isPaused)
            {
                time.Start();
                stopWatch.Start();
                BackgroundLoader.btnResume.Visible = false;
                BackgroundLoader.btnRestart.Visible = false;
                BackgroundLoader.btnExit.Visible = false;

                if (playVideo && BackgroundLoader.videoPlayer != null)
                {
                    BackgroundLoader.videoPlayer.Play();
                }
                BackgroundLoader.audioPlayer.Play();
            }
            else
            {
                time.Stop();
                stopWatch.Stop();
                BackgroundLoader.btnResume.Visible = true;
                BackgroundLoader.btnRestart.Visible = true;
                BackgroundLoader.btnExit.Visible = true;

                if (playVideo && BackgroundLoader.videoPlayer != null)
                {
                    BackgroundLoader.videoPlayer.Pause();
                }
                BackgroundLoader.audioPlayer.Pause();
            }
            isPaused = !isPaused;
        }

        internal void RestartGame()
        {
            Scoring.Reset(this);

            // 清除所有物块
            foreach (var tap in currentTaps)
            {
                tap.RemoveFromGame(this);
            }
            foreach (var breakTap in currentBreakTaps)
            {
                breakTap.RemoveFromGame(this);
            }
            foreach (var drag in currentDrags)
            {
                drag.RemoveFromGame(this);
            }
            foreach (var protectedTap in currentProtectedTap)
            {
                protectedTap.RemoveFromGame(this);
            }
            foreach (var protectedBreakTap in currentProtectedBreakTap)
            {
                protectedBreakTap.RemoveFromGame(this);
            }

            currentTaps.Clear();
            currentBreakTaps.Clear();
            currentDrags.Clear();
            currentProtectedTap.Clear();
            currentProtectedBreakTap.Clear();

            keysPress.Clear();

            tapsToRemove.Clear();
            breakTapsToRemove.Clear();
            dragsToRemove.Clear();
            protectedTapsToRemove.Clear();
            protectedBreakTapsToRemove.Clear();

            lastElapsedMilliseconds = 0;
            lastFrameTime = 0;

            map = BeatMapLoader.Instance.LoadBeatMap(songName, beatMapFileName);

            Scoring.InitializeAccuracy(map);

            switch (Settings.Instance.ScoringMethod)
            {
                case 1:
                    this.labelAccuracy.Text = "100.0000%";
                    break;
                case 2:
                    this.labelAccuracy.Text = "0.0000%";
                    break;
                case 3:
                    this.labelAccuracy.Text = map.HasBreakNotes() ? "101.0000%" : "100.0000%";
                    break;
                default:
                    this.labelAccuracy.Text = "--.----%";
                    break;
            }

            // 重新播放音频
            if (BackgroundLoader.audioPlayer != null)
            {
                // 释放旧 Media
                if (BackgroundLoader.audioPlayer.Media != null)
                {
                    BackgroundLoader.audioPlayer.Media.Dispose();
                    BackgroundLoader.audioPlayer.Media = null;
                }
                string audioPath = Path.Combine("Songs", map.Path, map.AudioPath);
                if (File.Exists(audioPath))
                {
                    using (var audioMedia = new LibVLCSharp.Shared.Media(BackgroundLoader.libVLC, audioPath))
                    {
                        BackgroundLoader.audioPlayer.Media = audioMedia;
                        BackgroundLoader.audioPlayer.Play();
                    }
                    // 注意：audioMedia 赋值给 MediaPlayer 后会被引用计数管理，using 不会提前释放
                }
            }

            // 重新播放视频
            if (playVideo)
            {
                // 释放旧 Media
                if (BackgroundLoader.videoPlayer != null && BackgroundLoader.videoPlayer.Media != null)
                {
                    BackgroundLoader.videoPlayer.Media.Dispose();
                    BackgroundLoader.videoPlayer.Media = null;
                }
                string videoPath = Path.Combine("Songs", map.Path, map.VideoPath);
                if (BackgroundLoader.videoPlayer != null && File.Exists(videoPath))
                {
                    using (var videoMedia = new LibVLCSharp.Shared.Media(BackgroundLoader.libVLC, videoPath))
                    {
                        BackgroundLoader.videoPlayer.Media = videoMedia;
                        BackgroundLoader.videoPlayer.Play();
                    }
                }
            }

            // 重置并重新启动 Stopwatch
            stopWatch.Reset();
            stopWatch.Start();

            // 停止并重新启动 Timer
            time.Stop();
            time.Start();

            // 隐藏暂停菜单并更新暂停状态
            BackgroundLoader.btnResume.Visible = false;
            BackgroundLoader.btnRestart.Visible = false;
            BackgroundLoader.btnExit.Visible = false;
            isPaused = false;
        }
    }
}
